import * as turf from '@turf/turf'
import { removeListByValue } from '../../utils/xingutils.js'

// 多面合并算法 找第一个面与其他所有面各合并一次，如果能合并就下一个，如果循环一遍都不能合并则返回合并失败
export function polygonsUnion(firstFeature, features) {
  if (features.length === 1) return firstFeature
  const polygonList = JSON.parse(JSON.stringify(features))

  let unionPolygon

  for (let i = 1; i < polygonList.length; i++) {
    const feature = features[i]

    unionPolygon = turf.union(firstFeature, feature)

    if (unionPolygon.geometry.type === 'Polygon') {
      // 删除这个面继续使用新数组递归
      removeListByValue(polygonList, 'id', feature.id)
      unionPolygon = polygonsUnion(unionPolygon, polygonList)
      break
    }
    if (i === polygonList.length - 1) {
      return unionPolygon
    }
  }
  return unionPolygon
}

// 单面切割算法
export function polygonSplit(splitLine, polygon) {
  const result = {
    success: true,
    message: '',
    polygons: []
  }
  // 把需要切割的面转成线
  const polygonConvertLine = turf.polygonToLine(polygon)
  //获取切割点
  const intersectsPoint = turf.lineIntersect(splitLine, polygonConvertLine)

  if (intersectsPoint.features.length !== 2) {
    result.success = false
    result.message = '切割线与多边形交点应该为2个, 当前交点个数为' + intersectsPoint.features.length
    return result
  }
  // 根据面线切割点切割切割线
  const splitAfterLine = turf.lineSlice(intersectsPoint.features[0], intersectsPoint.features[1], splitLine)
  // 切割选中面转化的线
  const slicedPolyLine = turf.lineSlice(intersectsPoint.features[0], intersectsPoint.features[1], polygonConvertLine)
  // 重新拼接多边形 存在 对接的问题 所以先进行判断 如何对接裁剪的多边形和裁剪线
  const resultPolyline1 = connectLine(slicedPolyLine, splitAfterLine)
  const resultPolygon1 = turf.lineToPolygon(resultPolyline1)

  result.polygons.push(resultPolygon1)

  // 构造切割的另一面多边形 ---
  const firstPointOnLine = isOnLine(turf.point(polygonConvertLine.geometry.coordinates[0]), slicedPolyLine)

  const pointList = []

  // 判断这个面的第一个点是否在切割后的面上
  if (firstPointOnLine) {
    for (let i = 0; i < polygonConvertLine.geometry.coordinates.length; i++) {
      const coordinate = polygonConvertLine.geometry.coordinates[i]

      if (!isOnLine(turf.point(coordinate), slicedPolyLine)) {
        pointList.push(coordinate)
      }
    }
  } else {
    let skipNum = 0 // 记录前面被跳过的点的个数

    let isStartPush = false

    for (let i = 0; i < polygonConvertLine.geometry.coordinates.length; i++) {
      const coordinate = polygonConvertLine.geometry.coordinates[i]

      if (!isOnLine(turf.point(coordinate), slicedPolyLine)) {
        if (isStartPush) {
          pointList.push(coordinate)
        } else {
          skipNum++
        }
      } else {
        isStartPush = true
      }
    }
    // 将前面跳过的点补充到 点数组中
    for (let i = 0; i < skipNum; i++) {
      pointList.push(polygonConvertLine.geometry.coordinates[i])
    }
  }
  // 重新拼接多边形
  const resultPolyline2 = connectLine(turf.lineString(pointList), splitAfterLine)
  // 线再转面
  const resultPolygon2 = turf.lineToPolygon(resultPolyline2)

  result.polygons.push(resultPolygon2)
  // 返回的是切割后的两个面
  return result
}

// 单线切割算法
export function lineSplit(splitLine, beSplitLine) {
  const result = {
    success: true,
    message: '',
    lines: []
  }
  //获取切割点
  const intersectsPoint = turf.lineIntersect(splitLine, beSplitLine)

  if (intersectsPoint.features.length !== 1) {
    result.success = false
    result.message = '切割线与多边形交点应该为1个, 当前交点个数为' + intersectsPoint.features.length
    return result
  }

  // 根据切割点和被切割线的起始点和终止点切割被切割线
  const points = beSplitLine.geometry.coordinates
  const startPoint = turf.point(points[0])
  const endPoint = turf.point(points[points.length - 1])

  const resultLine1 = turf.lineSlice(intersectsPoint.features[0], startPoint, beSplitLine)
  const resultLine2 = turf.lineSlice(intersectsPoint.features[0], endPoint, beSplitLine)
  result.lines.push(resultLine1)
  result.lines.push(resultLine2)

  // 返回的是切割后的两个线
  return result
}

/**
 * 连接两条线
 * 方法会将两条线段最近的一段直接连接
 */
function connectLine(line1, line2) {
  const line2_length = line2.geometry.coordinates.length

  const line1_startPoint = line1.geometry.coordinates[0]

  const line2_startPoint = line2.geometry.coordinates[0]

  const line2_endPoint = line2.geometry.coordinates[line2_length - 1]

  const pointList = []
  // 获取line1 所有点坐标

  for (let i = 0; i < line1.geometry.coordinates.length; i++) {
    const coordinate = line1.geometry.coordinates[i]

    pointList.push(coordinate)
  }

  // 判断两条线的 起点是否接近，如果接近 逆转line2线 进行连接
  if (turf.distance(line1_startPoint, line2_startPoint) < turf.distance(line1_startPoint, line2_endPoint)) {
    line2.geometry.coordinates = line2.geometry.coordinates.reverse()
  }
  for (let i = 0; i < line2.geometry.coordinates.length; i++) {
    const coordinate = line2.geometry.coordinates[i]

    pointList.push(coordinate)
  }
  return turf.lineString(pointList)
}

/**
 * 判断点是否在线里面
 * 注：线组成的坐标对比
 */
function isOnLine (point, splitLine) {
  for (let i = 0; i < splitLine.geometry.coordinates.length; i++) {
    const coordinate = splitLine.geometry.coordinates[i]

    if (point.geometry.coordinates[0] === coordinate[0] && point.geometry.coordinates[1] === coordinate[1]) {
      return true
    }
  }
  return false
}

// 线缓冲成墙面要素
export function lineBufferPolygon (lines) {
  const linePolygons = []
  for (const line of lines) {
    const width = line.properties.wallWidth / 2000
    const bufferPolygon = turf.buffer(line, width, {units: 'kilometers',steps:0})
    linePolygons.push(bufferPolygon)
  }
  return linePolygons
}